#region Apache License
//
// Licensed to the Apache Software Foundation (ASF) under one or more 
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership. 
// The ASF licenses this file to you under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with 
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion

using System;
using System.Collections;

using log4net.Util;

namespace log4net
{
    /// <summary>
    /// The log4net Thread Context.
    /// </summary>
    /// <remarks>
    /// <para>
    /// The <c>ThreadContext</c> provides a location for thread specific debugging 
    /// information to be stored.
    /// The <c>ThreadContext</c> properties override any <see cref="GlobalContext"/>
    /// properties with the same name.
    /// </para>
    /// <para>
    /// The thread context has a properties map and a stack.
    /// The properties and stack can 
    /// be included in the output of log messages. The <see cref="log4net.Layout.PatternLayout"/>
    /// supports selecting and outputting these properties.
    /// </para>
    /// <para>
    /// The Thread Context provides a diagnostic context for the current thread. 
    /// This is an instrument for distinguishing interleaved log
    /// output from different sources. Log output is typically interleaved
    /// when a server handles multiple clients near-simultaneously.
    /// </para>
    /// <para>
    /// The Thread Context is managed on a per thread basis.
    /// </para>
    /// </remarks>
    /// <example>Example of using the thread context properties to store a username.
    /// <code lang="C#">
    /// ThreadContext.Properties["user"] = userName;
    ///	log.Info("This log message has a ThreadContext Property called 'user'");
    /// </code>
    /// </example>
    /// <example>Example of how to push a message into the context stack
    /// <code lang="C#">
    ///	using(ThreadContext.Stacks["NDC"].Push("my context message"))
    ///	{
    ///		log.Info("This log message has a ThreadContext Stack message that includes 'my context message'");
    ///	
    ///	} // at the end of the using block the message is automatically popped 
    /// </code>
    /// </example>
    /// <threadsafety static="true" instance="true" />
    /// <author>Nicko Cadell</author>
    public sealed class ThreadContext
    {
        #region Private Instance Constructors

        /// <summary>
        /// Private Constructor. 
        /// </summary>
        /// <remarks>
        /// <para>
        /// Uses a private access modifier to prevent instantiation of this class.
        /// </para>
        /// </remarks>
        private ThreadContext()
        {
        }

        #endregion Private Instance Constructors

        #region Public Static Properties

        /// <summary>
        /// The thread properties map
        /// </summary>
        /// <value>
        /// The thread properties map
        /// </value>
        /// <remarks>
        /// <para>
        /// The <c>ThreadContext</c> properties override any <see cref="GlobalContext"/>
        /// properties with the same name.
        /// </para>
        /// </remarks>
        public static ThreadContextProperties Properties
        {
            get { return s_properties; }
        }

        /// <summary>
        /// The thread stacks
        /// </summary>
        /// <value>
        /// stack map
        /// </value>
        /// <remarks>
        /// <para>
        /// The thread local stacks.
        /// </para>
        /// </remarks>
        public static ThreadContextStacks Stacks
        {
            get { return s_stacks; }
        }

        #endregion Public Static Properties

        #region Private Static Fields

        /// <summary>
        /// The thread context properties instance
        /// </summary>
        private readonly static ThreadContextProperties s_properties = new ThreadContextProperties();

        /// <summary>
        /// The thread context stacks instance
        /// </summary>
        private readonly static ThreadContextStacks s_stacks = new ThreadContextStacks(s_properties);

        #endregion Private Static Fields
    }
}
